package mybatis_plus;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.mapping.*;

/**
 * mybatis plus 自定义流式查询方法
 * 具体方法
 * void bigDataSelect(Wrapper<T> queryWrapper, ResultHandler<T> handler);
 */
public class BigDataSelect extends AbstractMethod {

	private final static int FETCH_SIZE = 100; //每次获取量
	
	private final static ResultSetType RESULT_SET_TYPE = ResultSetType.FORWARD_ONLY; //游标只向前滚动
	
	@Override
	public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
		String sql = String.format("<script>SELECT %s FROM %s %s\n</script>", sqlSelectColumns(tableInfo, true), tableInfo.getTableName(), sqlWhereEntityWrapper(true, tableInfo));
		SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
		return this.addSelectMappedStatementForOther(mapperClass, "bigDataSelect", sqlSource, tableInfo.getEntityType());
	}

	/**
     * 是否已经存在MappedStatement
     * 实际上是重写了父类的方法
     * @param mappedStatement MappedStatement
     * @return true or false
     */
    private boolean hasMappedStatement(String mappedStatement) {
        return configuration.hasStatement(mappedStatement, false);
    }
	
	@Override
	protected MappedStatement addMappedStatement(Class<?> mapperClass, String id, SqlSource sqlSource,
			SqlCommandType sqlCommandType, Class<?> parameterType, String resultMap, Class<?> resultType,
			KeyGenerator keyGenerator, String keyProperty, String keyColumn) {
		
		String statementName = mapperClass.getName() + DOT + id;
        if (hasMappedStatement(statementName)) {
            logger.warn(LEFT_SQ_BRACKET + statementName + "] Has been loaded by XML or SqlProvider or Mybatis's Annotation, so ignoring this injection for [" + getClass() + RIGHT_SQ_BRACKET);
            return null;
        }
        /* 缓存逻辑处理 */
        boolean isSelect = false;
        if (sqlCommandType == SqlCommandType.SELECT) {
            isSelect = true;
        }
		
        return builderAssistant.addMappedStatement(id, sqlSource, StatementType.PREPARED, sqlCommandType,
        		FETCH_SIZE, null, null, parameterType, resultMap, resultType,
        		RESULT_SET_TYPE, !isSelect, isSelect, false, keyGenerator, keyProperty, keyColumn,
                configuration.getDatabaseId(), languageDriver, null);
	}
}
